<?php
/**
 * @title 可信任程序通信验证机制
 * @author JohnnyDen <413819942@qq.com>
 * @date 2017年12月5日
 */
namespace api;

class Auth {
    
    //加签方式(func)
    static private $signType    = 'md5';
    
    //请求最大延时(s)
    static private $maxTimeDelay   = false; //不校验
    
    //当前请求的client
    static private $client      = null;
    
    static private $needCrypt   = false;
    
    /**
     * 验签
     * @param string $sign 客户端发送的签名字符串
     * @param string $client_id 客户端帐号
     * @param int $timestamp 请求时间戳
     * @param array $sign_params 请求的其它参数
     * @return boolean
     */
    static public function checkSign($sign, $client_id, $timestamp, $sign_params = []) {
        
        if (!$sign || !$client_id || !$timestamp) {
            return false;
        }
        self::$client   = config('AuthClient.'.$client_id);
        if (!self::$client) {
            return false;
        }
        define('RSA_PRIVATE_KEY', self::$client['private_key']);
        define('RSA_PUBLIC_KEY', self::$client['public_key']);
        
        $secret     = self::$client['client_secret'];
        
        if ($sign_params) {
            sort($sign_params);
            array_unshift($sign_params, $secret, $client_id, $timestamp);
        } else {
            $sign_params = [$secret, $client_id, $timestamp];
        }
        
        $func = self::$signType;
        $local_sign = $func(implode('-', $sign_params));
        
        return $sign !=  $local_sign ? false : true;
    }
    
    /**
     * 延时限制验证，防重放攻击
     * @param int $timestamp 请求时间
     * @return boolean
     */
    static public function checkRequestTime($timestamp) {
        if (self::$maxTimeDelay && (!$timestamp || $timestamp + self::$maxTimeDelay <= $_SERVER['REQUEST_TIME'])) {
            return false;
        } else {
            return true;
        }
    }
    
    /**
     * 校验当前请求是否是加密通信
     * @param int $crypt_level
     * @param int $action_crypt_level
     * @return boolean
     */
    static public function checkCryptLevel($crypt_level, $action_crypt_level) {
        $crypt_level_floor  = (int)self::$client['crypt_level_floor'];
        if ((int)$crypt_level !== $crypt_level_floor) {
            return null;
        }
        if ((int)$action_crypt_level > $crypt_level_floor) {
            self::$needCrypt    = true;
        } else {
            self::$needCrypt    = false;
        }
        
        return self::$needCrypt;
    }
    
    /**
     * 判断当前输出是否要加密传输
     * @return boolean
     */
    static public function needCrypt() {
        return self::$needCrypt;
    }
    
    /**
     * 加密数据
     * @param string $data 要加密的数据
     */
    static public function encrypt($data) {
        if (!$data) {
            return null;
        }
        
        $des_key    = self::$client['client_id'].'-'.rand(10000000, 99999999).'-'.time();
        $des_key    = $des_key.'-'.md5($des_key);
        
        $data       = \api\crypt\Des::encrypt($data, $des_key);
        $des_key    = \api\crypt\Rsa::privEncrypt($des_key);
        
        return json_encode([
            'key'   => $des_key,
            'data'  => $data,
        ]);
    }
    
    /**
     * 解密数据
     * @param string $key 钥匙
     * @param string $data 加密的数据
     */
    static public function decrypt($key, $data) {
        if (!$key || !$data) {
            return null;
        }
        
        //自定义的解密函数调用
        $des_key    = \api\crypt\Rsa::privDecrypt($key);
        return json_decode(\api\crypt\Des::decrypt($data, $des_key), true);
    }
    
}